﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace NFit.Core.Errors
{
    /// <summary>
    /// Kind of missing element
    /// </summary>
    public enum ElementKind
    {
        /// <summary>Keyword element</summary>
        Keyword,
        /// <summary>Property or field</summary>
        PropertyOrField,
        /// <summary>Method element</summary>
        Method,
        /// <summary>Fixture element</summary>
        Fixture,
        /// <summary>Specification element</summary>
        Specification
    }

    /// <summary>
    /// Error attached if some element is missing
    /// </summary>
    public class ElementNotFoundError : NFitError
    {
        /// <summary>
        /// Kind of missing element
        /// </summary>
        public ElementKind Kind { get; private set;}

        /// <summary>
        /// Name of the missing element
        /// </summary>
        public string ElementName { get; private set; }

        /// <summary>
        /// Target of the missing element
        /// </summary>
        public string ElementTarget { get; private set; }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="kind"></param>
        /// <param name="elementName"></param>
        /// <param name="elementTarget"></param>
        public ElementNotFoundError(ElementKind kind, string elementName, string elementTarget)
        {
            Kind = kind;
            ElementName = elementName;
            ElementTarget = elementTarget;
        }

        /// <summary>
        /// Factory method for a missing keyword
        /// </summary>
        /// <param name="elementName"></param>
        /// <returns></returns>
        public static ElementNotFoundError Keyword(string elementName)
        {
            return new ElementNotFoundError(ElementKind.Keyword,elementName,null);
        }

        /// <summary>
        /// Factory method for a missing specification
        /// </summary>
        /// <param name="elementName"></param>
        /// <returns></returns>
        public static ElementNotFoundError Specification(string elementName)
        {
            return new ElementNotFoundError(ElementKind.Specification, elementName, null);
        }

        /// <summary>
        /// Factory method for a missing property or field
        /// </summary>
        /// <param name="elementName"></param>
        /// <param name="elementTarget"></param>
        /// <returns></returns>
        public static ElementNotFoundError PropertyOrField(string elementName, string elementTarget)
        {
            return new ElementNotFoundError(ElementKind.PropertyOrField, elementName, elementTarget);
        }

        /// <summary>
        /// Factory method for a missing method
        /// </summary>
        /// <param name="elementName"></param>
        /// <param name="elementTarget"></param>
        /// <returns></returns>
        public static ElementNotFoundError Method(string elementName, string elementTarget)
        {
            return new ElementNotFoundError(ElementKind.Method, elementName, elementTarget);
        }

        /// <summary>
        /// Factory method for a missing fixture
        /// </summary>
        /// <param name="elementName"></param>
        /// <returns></returns>
        public static ElementNotFoundError Fixture(string elementName)
        {
            return new ElementNotFoundError(ElementKind.Fixture, elementName, null);
        }

        /// <summary>
        /// Factory method for a missing fixture
        /// </summary>
        /// <param name="elementName"></param>
        /// <param name="elementTarget"></param>
        /// <returns></returns>
        public static ElementNotFoundError Fixture(string elementName, string elementTarget)
        {
            return new ElementNotFoundError(ElementKind.Fixture, elementName, elementTarget);
        }

        /// <summary>
        /// Get a representation of the error
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return string.Format("named element {0} of kind {2} is missing on {1}", this.ElementName, this.ElementTarget, this.Kind);
        }
    }
}
